Compare commits

..

2 Commits

Author SHA1 Message Date
6e6df73007 module 7 finished 2026-03-05 15:21:29 +01:00
516ef290a7 module 7 ex 3 2026-03-03 16:00:55 +01:00
16 changed files with 373 additions and 23 deletions

View File

View File

@@ -16,6 +16,4 @@ class Card(ABC):
return res
def is_playable(self, available_mana: int) -> bool:
if available_mana > 5:
return True
return False
return available_mana > 5

View File

@@ -1,5 +1,5 @@
def main():
from CreatureCard import CreatureCard
def main() -> None:
from .CreatureCard import CreatureCard
game_state = {"player": "michel", "mana": 6}
print("=== DataDeck Card Foundation ===\n")
@@ -7,7 +7,9 @@ def main():
creature_card = CreatureCard("Fire Dragon", 5, "Legendary", 7, 5)
print(f"CreatureCard info:\n{creature_card.get_card_info()}")
print("\nPlaying Fire Dragon with 6 mana available:")
print(f"Playable: {creature_card.is_playable(game_state['mana'])}")
playable = creature_card.is_playable(game_state["mana"])
print(f"Playable: {playable}")
if playable:
print(f"Play result: {creature_card.play(game_state)}")
print("\nFire Dragon attacks Goblin Warrior:")
print(f"Attack result: {creature_card.attack_target('Goblin Warrior')}")

View File

@@ -4,10 +4,11 @@ from typing import Union
class SpellCard(Card):
def __init__(
self, name: str, cost: int, rarity: str, effect_type: str
self, name: str, cost: int, rarity: str, effect_type: str, mana: int
) -> None:
super().__init__(name, cost, rarity)
self.effect_type = effect_type
self.mana = mana
def play(self, game_state: dict) -> dict:
try:

View File

@@ -1,4 +1,4 @@
def main():
def main() -> None:
from .Deck import Deck
from .SpellCard import SpellCard
from .ArtifactCard import ArtifactCard
@@ -8,7 +8,7 @@ def main():
deck = Deck()
print("Building deck with different card types...")
deck.add_card(
SpellCard("Lightning Bolt", 5, "Common", "Deal 3 dammage to target")
SpellCard("Lightning Bolt", 5, "Common", "Deal 3 dammage to target", 5)
)
deck.add_card(
ArtifactCard(

View File

@@ -1,4 +1,4 @@
def main():
def main() -> None:
from .EliteCard import EliteCard
print("=== DataDeck Ability System ===\n")

View File

@@ -1,9 +1,22 @@
from .GameStrategy import GameStrategy
from operator import attrgetter
class AgressiveStrategy(GameStrategy):
def execute_turn(self, hand: list, battlefield: list) -> dict: ...
def execute_turn(self, hand: list, battlefield: list) -> dict:
return {
"cards_played": [card.name for card in hand],
"mana_used": 5,
"targets_attacked": battlefield,
"damage_dealt": 8,
}
def get_strategy_name(self) -> str: ...
def get_strategy_name(self) -> str:
return "Aggressive"
def prioritize_targets(self, available_targets: list) -> list: ...
def prioritize_targets(self, available_targets: list) -> list:
try:
return sorted(available_targets, key=attrgetter("health"))
except Exception as err:
print(err)
return available_targets

View File

@@ -2,6 +2,7 @@ from .CardFactory import CardFactory
from random import choice
from ex0 import Card, CreatureCard
from ex1 import SpellCard, ArtifactCard
from copy import deepcopy
creature_cards = [
CreatureCard("Fire Dragon", 20, "Rare", 7, 20),
@@ -9,10 +10,10 @@ creature_cards = [
]
spell_cards = [
SpellCard("Fire Ball", 5, "Rare", "Decrase health by 1 for 3 round"),
SpellCard("Ice Spike", 3, "Common", "Reduce damage by 2 for 1 round"),
SpellCard("Fire Ball", 5, "Rare", "Decrase health by 1 for 3 round", 5),
SpellCard("Ice Spike", 3, "Common", "Reduce damage by 2 for 1 round", 3),
SpellCard(
"Lightning bolt", 10, "Legendary", "Card can't play for 3 round"
"Lightning bolt", 10, "Legendary", "Card can't play for 3 round", 10
),
]
@@ -20,13 +21,15 @@ artifact_cards = [
ArtifactCard(
"Mana Ring", 2, "Common", 3, "Increase mana by 1 for each round"
),
ArtifactCard("Witch Staff", 6, "Legendary", 5, ""),
ArtifactCard(
"Witch Staff", 6, "Legendary", 5, "Decrease 5 mana of a card"
),
]
class FantasyCardFactory(CardFactory):
def create_creature(self, name_or_power: str | int | None = None) -> Card:
card = choice(creature_cards)
card = deepcopy(choice(creature_cards))
if isinstance(name_or_power, str):
card.name = name_or_power
elif isinstance(name_or_power, int):
@@ -34,13 +37,40 @@ class FantasyCardFactory(CardFactory):
return card
def create_spell(self, name_or_power: str | int | None = None) -> Card:
return super().create_spell(name_or_power)
card = deepcopy(choice(spell_cards))
if isinstance(name_or_power, str):
card.name = name_or_power
elif isinstance(name_or_power, int):
card.mana = name_or_power
return card
def create_artifact(self, name_or_power: str | int | None = None) -> Card:
return super().create_artifact(name_or_power)
card = deepcopy(choice(artifact_cards))
if isinstance(name_or_power, str):
card.name = name_or_power
elif isinstance(name_or_power, int):
card.durability = name_or_power
return card
def create_themed_deck(self, size: int) -> dict:
return super().create_themed_deck(size)
deck: dict[str, list[Card]] = {}
for _ in range(size):
card = choice(
[
self.create_creature(),
self.create_artifact(),
self.create_spell(),
]
)
if card.name in deck:
deck[card.name] += [card]
else:
deck[card.name] = [card]
return deck
def get_supported_types(self) -> dict:
return super().get_supported_types()
return {
"creatures": [card.name for card in creature_cards],
"spells": [card.name for card in spell_cards],
"artifacts": [card.name for card in artifact_cards],
}

View File

@@ -0,0 +1,41 @@
from .CardFactory import CardFactory
from .GameStrategy import GameStrategy
class GameEngine:
def __init__(self) -> None:
self.turns_simulated = 0
self.total_damage = 0
self.created_cards = 0
def configure_engine(
self, factory: CardFactory, strategy: GameStrategy
) -> None:
self.factory = factory
self.strategy = strategy
def simulate_turn(self) -> dict:
try:
cards = []
deck = self.factory.create_themed_deck(3).values()
for card_list in deck:
for card in card_list:
cards += [card]
hand = [f"{card.name} ({card.cost})" for card in cards]
print(f"Hand: {hand}")
turn = self.strategy.execute_turn(cards, ["Enemy player"])
self.total_damage += turn["damage_dealt"]
self.created_cards += 3
self.turns_simulated += 1
return turn
except Exception as err:
print(err)
return {}
def get_engine_status(self) -> dict:
return {
"turns_simulated": self.turns_simulated,
"strategy_used": self.strategy.get_strategy_name(),
"total_damage": self.total_damage,
"cards_created": self.created_cards,
}

View File

@@ -0,0 +1,15 @@
from .AggresiveStrategy import AgressiveStrategy
from .CardFactory import CardFactory
from .FantasyCardFactory import FantasyCardFactory
from .GameEngine import GameEngine
from .GameStrategy import GameStrategy
__version__ = "1.0.0"
__author__ = "dgaillet"
__all__ = [
"AgressiveStrategy",
"CardFactory",
"FantasyCardFactory",
"GameEngine",
"GameStrategy",
]

View File

@@ -0,0 +1,27 @@
from .GameEngine import GameEngine
from .FantasyCardFactory import FantasyCardFactory
from .AggresiveStrategy import AgressiveStrategy
def main() -> None:
print("=== DataDeck Game Engine ===\n")
print("Configuring Fantasy Card Game...")
engine = GameEngine()
engine.configure_engine(FantasyCardFactory(), AgressiveStrategy())
print(f"Factory: {engine.factory.__class__.__name__}")
print(f"Strategy: {engine.strategy.__class__.__name__}")
print(f"Available types: {engine.factory.get_supported_types()}")
print("\nSimulating aggressive turn...")
actions = engine.simulate_turn()
print("\nTurn execution:")
print(f"Strategy: {engine.strategy.get_strategy_name()}")
print(f"Actions: {actions}")
print("\nGame Report:")
print(f"{engine.get_engine_status()}")
print(
"\nAbstract Factory + Strategy Pattern: Maximum flexibility achieved!"
)
if __name__ == "__main__":
main()

15
07/ex4/Rankable.py Normal file
View File

@@ -0,0 +1,15 @@
from abc import ABC, abstractmethod
class Rankable(ABC):
@abstractmethod
def calculate_rating(self) -> int: ...
@abstractmethod
def update_wins(self, wins: int) -> None: ...
@abstractmethod
def update_losses(self, losses: int) -> None: ...
@abstractmethod
def get_rank_info(self) -> dict: ...

97
07/ex4/TournamentCard.py Normal file
View File

@@ -0,0 +1,97 @@
from ex0 import Card
from ex2 import Combatable
from .Rankable import Rankable
from typing import Union
class TournamentCard(Card, Combatable, Rankable):
def __init__(
self,
id: str,
name: str,
cost: int,
rarity: str,
damage: int,
health: int,
shield: int,
rank: int,
) -> None:
super().__init__(name, cost, rarity)
self.id = id
self.looses = 0
self.wins = 0
self.damage = damage
self.health = health
self.shield = shield
self.rank = rank
def play(self, game_state: dict) -> dict:
try:
res: dict[str, int | str] = {}
if game_state["mana"] < 2:
raise Exception("Not enough mana")
res["card_played"] = self.name
res["mana_used"] = 2
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 calculate_rating(self) -> int:
try:
if self.wins == 0:
return self.rank - self.looses * 10
return self.rank + (int(self.wins / self.looses) * 10)
except ZeroDivisionError:
return self.rank + self.wins * 10
except Exception as err:
print(err)
return self.rank
def get_tournament_stats(self) -> dict:
return {
"Interfaces": "[Card, Combatable, Rankable]",
"Rating": self.calculate_rating(),
"Record": f"{self.wins}-{self.looses}",
}
def update_wins(self, wins: int) -> None:
self.wins = wins
def update_losses(self, losses: int) -> None:
self.looses = losses
def get_rank_info(self) -> dict:
return {
"wins": self.wins,
"looses": self.looses,
"rank": self.rank,
}

View File

@@ -0,0 +1,65 @@
from .TournamentCard import TournamentCard
class TournamentPlatform:
def __init__(self) -> None:
self.cards: list[TournamentCard] = []
self.math_played = 0
def register_card(self, card: TournamentCard) -> str:
try:
stats = card.get_tournament_stats()
res = f"{card.name} (ID: {card.id}):\n\
- Interfaces: {stats['Interfaces']}\n\
- Rating: {stats['Rating']}\n\
- Record: {stats['Record']}\n"
self.cards += [card]
return res
except Exception:
print("Invalid card")
return "error"
def create_match(self, card1_id: str, card2_id: str) -> dict:
from random import shuffle
try:
cards = [
card
for card in self.cards
if card.id == card1_id or card.id == card2_id
]
if len(cards) != 2:
raise Exception(
"At least once of cards id provide isn't in platform"
)
shuffle(cards)
winner = cards.pop()
loser = cards.pop()
winner.update_wins(winner.wins + 1)
loser.update_losses(loser.looses + 1)
self.math_played += 1
return {
"winner": winner.id,
"loser": loser.id,
"winner_rating": winner.calculate_rating(),
"loser_rating": loser.calculate_rating(),
}
except Exception as err:
print(err)
return {}
def get_leaderboard(self) -> list:
return sorted(
self.cards, key=lambda x: x.calculate_rating(), reverse=True
)
def generate_tournament_report(self) -> dict:
return {
"total_cards": len(self.cards),
"mathes_played": self.math_played,
"avg_rating": int(
sum([card.calculate_rating() for card in self.cards])
/ len(self.cards)
),
"platform_status": "active",
}

7
07/ex4/__init__.py Normal file
View File

@@ -0,0 +1,7 @@
from .Rankable import Rankable
from .TournamentCard import TournamentCard
from .TournamentPlatform import TournamentPlatform
__version__ = "1.0.0"
__author__ = "dgaillet"
__all__ = ["Rankable", "TournamentCard", "TournamentPlatform"]

39
07/ex4/main.py Normal file
View File

@@ -0,0 +1,39 @@
from .TournamentCard import TournamentCard
from .TournamentPlatform import TournamentPlatform
def main() -> None:
print("=== DataDeck Tournament Platform ===\n")
print("Registering Tournament Cards...\n")
platform = TournamentPlatform()
print(
platform.register_card(
TournamentCard(
"dragon_001", "Fire Dragon", 20, "Rare", 15, 25, 5, 1200
)
)
)
print(
platform.register_card(
TournamentCard(
"wizard_001", "Ice Wizard", 15, "common", 10, 30, 4, 1150
)
)
)
print("Creating tournament match...")
match_res = platform.create_match("dragon_001", "wizard_001")
print(f"Math result: {match_res}\n")
print("Tournament Leaderboard:")
leaderboard = platform.get_leaderboard()
for i in range(len(leaderboard)):
print(f"{i + 1}. {leaderboard[i].name} - Rating:\
{leaderboard[i].calculate_rating()}\
({leaderboard[i].get_tournament_stats()['Record']})")
print("\nPlatform Report:")
print(platform.generate_tournament_report())
print("\n=== Tournament Platform Successfully Deployed! ===")
print("All abstract patterns working together harmoniously!")
if __name__ == "__main__":
main()