From 164445bb4213d96c77d7cac75f6fb6e04a5b580e Mon Sep 17 00:00:00 2001 From: David GAILLETON Date: Mon, 2 Mar 2026 15:49:13 +0100 Subject: [PATCH] module 7 ex 0 to 2 --- 07/__init__.py | 0 07/ex0/Card.py | 1 - 07/ex0/CreatureCard.py | 2 +- 07/ex1/ArtifactCard.py | 11 +++++- 07/ex1/Deck.py | 6 ++- 07/ex1/SpellCard.py | 8 ++-- 07/ex1/main.py | 32 ++++++++++++++++ 07/ex2/Combatable.py | 12 ++++++ 07/ex2/EliteCard.py | 87 ++++++++++++++++++++++++++++++++++++++++++ 07/ex2/Magical.py | 12 ++++++ 07/ex2/__init__.py | 7 ++++ 07/ex2/main.py | 21 ++++++++++ 12 files changed, 189 insertions(+), 10 deletions(-) create mode 100644 07/__init__.py create mode 100644 07/ex2/Combatable.py create mode 100644 07/ex2/EliteCard.py create mode 100644 07/ex2/Magical.py create mode 100644 07/ex2/__init__.py create mode 100644 07/ex2/main.py diff --git a/07/__init__.py b/07/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/07/ex0/Card.py b/07/ex0/Card.py index 2d15e3b..291a42f 100644 --- a/07/ex0/Card.py +++ b/07/ex0/Card.py @@ -1,5 +1,4 @@ from abc import ABC, abstractmethod -from typing import Union class Card(ABC): diff --git a/07/ex0/CreatureCard.py b/07/ex0/CreatureCard.py index ab0fb6e..5edfddf 100644 --- a/07/ex0/CreatureCard.py +++ b/07/ex0/CreatureCard.py @@ -1,4 +1,4 @@ -from Card import Card +from .Card import Card from typing import Dict, Union diff --git a/07/ex1/ArtifactCard.py b/07/ex1/ArtifactCard.py index 47d41fa..feac99e 100644 --- a/07/ex1/ArtifactCard.py +++ b/07/ex1/ArtifactCard.py @@ -1,4 +1,4 @@ -from ex0.Card import Card +from ex0 import Card from typing import Union @@ -24,4 +24,11 @@ class ArtifactCard(Card): return {} def activate_ability(self) -> dict: - pass + if self.durability <= 0: + return { + "name": self.name, + "durability": self.durability, + "destroyed": True, + } + self.durability -= 1 + return self.get_card_info() diff --git a/07/ex1/Deck.py b/07/ex1/Deck.py index e4b42d1..102359e 100644 --- a/07/ex1/Deck.py +++ b/07/ex1/Deck.py @@ -21,10 +21,12 @@ class Deck: shuffle(self.cards) def draw_card(self) -> Card: - pass + self.shuffle() + return self.cards.pop() def get_deck_stats(self) -> dict: - from . import ArtifactCard, SpellCard + from .ArtifactCard import ArtifactCard + from .SpellCard import SpellCard creatures = 0 spells = 0 diff --git a/07/ex1/SpellCard.py b/07/ex1/SpellCard.py index b797dc3..ccb985b 100644 --- a/07/ex1/SpellCard.py +++ b/07/ex1/SpellCard.py @@ -1,4 +1,4 @@ -from ex0.Card import Card +from ex0 import Card from typing import Union @@ -10,7 +10,7 @@ class SpellCard(Card): self.effect_type = effect_type def play(self, game_state: dict) -> dict: - try: + try: res: dict[str, Union[int, str]] = {} if game_state["mana"] < 3: raise Exception("Not enough mana") @@ -22,5 +22,5 @@ class SpellCard(Card): print(err) return {} - def resolve_effect(self, targets: list) -> dict: - pass + def resolve_effect(self, targets: list) -> dict: + return {"card": self.name, "targets": targets, "resolved": True} diff --git a/07/ex1/main.py b/07/ex1/main.py index e69de29..4fb9256 100644 --- a/07/ex1/main.py +++ b/07/ex1/main.py @@ -0,0 +1,32 @@ +def main(): + from .Deck import Deck + from .SpellCard import SpellCard + from .ArtifactCard import ArtifactCard + from ex0 import CreatureCard + + print("=== DataDeck Deck Builder ===\n") + deck = Deck() + print("Building deck with different card types...") + deck.add_card( + SpellCard("Lightning Bolt", 5, "Common", "Deal 3 dammage to target") + ) + deck.add_card( + ArtifactCard( + "Mana Crystal", 7, "Medium", 1, "Permanent: +1 mana per turn" + ) + ) + deck.add_card(CreatureCard("Fire dragon", 10, "Rare", 15, 20)) + print(f"Deck stats: {deck.get_deck_stats()}") + print("\nDrawing and playing cards:\n") + for _ in range(deck.get_deck_stats()["total_card"]): + try: + card = deck.draw_card() + print(f"Drew: {card.name} ({card.__class__.__name__})") + print(f"{card.play({'mana': 5})}\n") + except Exception as err: + print(err) + print("Polymorphism in action: Same interface, different card behaviors!") + + +if __name__ == "__main__": + main() diff --git a/07/ex2/Combatable.py b/07/ex2/Combatable.py new file mode 100644 index 0000000..4a69b3a --- /dev/null +++ b/07/ex2/Combatable.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod + + +class Combatable(ABC): + @abstractmethod + def attack(self, target: str) -> dict: ... + + @abstractmethod + def defend(self, incoming_damage: int) -> dict: ... + + @abstractmethod + def get_combate_stats(self) -> dict: ... diff --git a/07/ex2/EliteCard.py b/07/ex2/EliteCard.py new file mode 100644 index 0000000..ac61db6 --- /dev/null +++ b/07/ex2/EliteCard.py @@ -0,0 +1,87 @@ +from ex0.Card import Card +from .Combatable import Combatable +from .Magical import Magical +from typing import Union + + +class EliteCard(Card, Combatable, Magical): + def __init__( + self, + name: str, + cost: int, + rarity: str, + damage: int, + health: int, + shield: int, + initial_mana: int, + spell_cost: int, + ) -> None: + super().__init__(name, cost, rarity) + self.damage = damage + self.health = health + self.shield = shield + self.mana = initial_mana + self.spell_cost = spell_cost + + def play(self, game_state: dict) -> dict: + try: + res: dict[str, int | str] = {} + if game_state["mana"] < 5: + raise Exception("Not enough mana") + res["card_played"] = self.name + res["mana_used"] = 5 + res["effect"] = "Creature summoned to battlefield" + return res + except Exception as err: + print(err) + return {} + + def attack(self, target: str) -> dict: + return { + "attacker": self.name, + "target": target, + "damage_dealt": self.damage, + "combat_type": "melee", + } + + def defend(self, incoming_damage: int) -> dict: + res: dict[str, Union[str, int, bool]] = {} + res["defender"] = self.name + if incoming_damage <= self.shield: + res["damage_blocked"] = incoming_damage + res["damage_taken"] = 0 + else: + res["damage_taken"] = incoming_damage - self.shield + res["damage_blocked"] = self.shield + self.health -= incoming_damage - self.shield + res["still_alive"] = self.health > 0 + return res + + def get_combate_stats(self) -> dict: + return { + "damage": self.damage, + "health": self.health, + "shield": self.shield, + } + + def cast_spell(self, spell_name: str, targets: list) -> dict: + try: + if self.mana < self.spell_cost: + raise Exception("Not enough mana") + self.mana -= self.spell_cost + return { + "caster": self.name, + "spell": spell_name, + "targets": targets, + "mana_used": self.spell_cost, + } + except Exception as err: + print(err) + return {} + + def channel_mana(self, amount: int) -> dict: + self.mana += amount + return {"channeled": amount, "total_mana": self.mana} + + def get_magic_stats(self) -> dict: + return {"mana": self.mana, "spell cost": self.spell_cost} diff --git a/07/ex2/Magical.py b/07/ex2/Magical.py new file mode 100644 index 0000000..68b3687 --- /dev/null +++ b/07/ex2/Magical.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod + + +class Magical(ABC): + @abstractmethod + def cast_spell(self, spell_name: str, targets: list) -> dict: ... + + @abstractmethod + def channel_mana(self, amount: int) -> dict: ... + + @abstractmethod + def get_magic_stats(self) -> dict: ... diff --git a/07/ex2/__init__.py b/07/ex2/__init__.py new file mode 100644 index 0000000..8c32359 --- /dev/null +++ b/07/ex2/__init__.py @@ -0,0 +1,7 @@ +from .Combatable import Combatable +from .Magical import Magical +from .EliteCard import EliteCard + +__version__ = "1.0.0" +__author__ = "dgaillet" +__all__ = ["Combatable", "Magical", "EliteCard"] diff --git a/07/ex2/main.py b/07/ex2/main.py new file mode 100644 index 0000000..290af59 --- /dev/null +++ b/07/ex2/main.py @@ -0,0 +1,21 @@ +def main(): + from .EliteCard import EliteCard + + print("=== DataDeck Ability System ===\n") + card = EliteCard("Arcane Warrior", 25, "Legendary", 5, 20, 3, 4, 4) + print("EliteCard capabilities:") + print("- Card: ['play', 'get_card_info', 'is_playable']") + print("- Combatable: ['attack', 'defend', 'get_combat_stats']") + print("- Magical: ['cast_spell', 'channel_mana', 'get_magic_stats']") + print("\nPlaying Arcane Warrior (Elite Card):\n") + print("Combat phase:") + print(f"Attack result: {card.attack('Enemy')}") + print(f"Defense result: {card.defend(5)}") + print("\nMagic phase:") + print(f"Spell cast: {card.cast_spell('Fireball', ['Enemy1', 'Enemy2'])}") + print(f"Mana channel: {card.channel_mana(3)}") + print("Multiple interface implementation successful!") + + +if __name__ == "__main__": + main()