I'm trying to make a Yu-Gi-Oh! card game with Pygame that works as a very simplified version of the video game versions (i.e. monster cards only, and they can only attack, thus for now they should only have attack points as attributes). But now I'm struggling to implement the cards' atk points as attributes for the battle system, since each card is represented by a pygame sprite taken from a list of sprites from the very same class, instead of each card being its own instance of its own class for allowing proper attribute implementation. I'm really stuck on this, so would really really appreciate any solutions. I thought about implementing each card on its own class as just mentioned, but since i wouldn't be able to know which cards have already been drawn at a given moment, i don't see how i would be able to properly filter the available cards to be drawn from the deck (the list named self.deck at card.py) at a given moment through the card list without repeating some of them that should be unavailable. These are the relevant parts of code from the project: From the main game file (card_game.py) import sys import pygame from card import Card from card import EnemyCards from board import Board from life_points import LifePoints from deck import Deck from deck import CPUDeck from settings import Settings import random, os class CardGame: """Overall class to manage game assets and behavior.""" def __init__(self): """Innitialize the game and create game resources.""" pygame.init() self.settings = Settings() self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) self.screen_rect = self.screen.get_rect() self.settings.screen_width = self.screen.get_rect().width self.settings.screen_height = self.screen.get_rect().height pygame.display.set_caption("Card Game") self.lp = LifePoints(self) self.cards = Card(self) self.card_1_rect = self.cards.rect_1 self.card_2_rect = self.cards.rect_2 self.card_3_rect = self.cards.rect_3 self.card_4_rect = self.cards.rect_4 self.card_5_rect = self.cards.rect_5 self.cpu_cards = EnemyCards(self) self.cpu_card_1_rect = self.cpu_cards.rect_1 self.cpu_card_2_rect = self.cpu_cards.rect_2 self.cpu_card_3_rect = self.cpu_cards.rect_3 self.cpu_card_4_rect = self.cpu_cards.rect_4 self.cpu_card_5_rect = self.cpu_cards.rect_5 self.board = Board(self) self.deck = Deck(self) self.deck.position_deck() self.cpu_deck = CPUDeck(self) self.cpu_deck.position_deck() def run_game(self): """Start the main loop for the game.""" while True: # Watch for keyboard and mouse events. self._check_events() self._update_screen() def _check_events(self): """Respond to keypresses and mouse events.""" for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() if self.player_turn == True: self._check_card_clicked(mouse_pos) else: self._check_cpu_card_clicked(mouse_pos) if self.deck.deck_image_rect.collidepoint(mouse_pos): self.cards.draw_card() elif self.cpu_deck.deck_image_rect.collidepoint(mouse_pos): self.cpu_cards.draw_card() def _check_card_clicked(self, mouse_pos): """Checks if the player clicked on the card and if so, puts it on the board.""" card_1_clicked = self.card_1_rect.collidepoint(mouse_pos) card_2_clicked = self.card_2_rect.collidepoint(mous e_pos) card_3_clicked = self.card_3_rect.collidepoint(mouse_pos) card_4_clicked = self.card_4_rect.collidepoint(mouse_pos) card_5_clicked = self.card_5_rect.collidepoint(mouse_pos) if card_1_clicked: self.card_1_rect.center = (419, 594) elif card_2_clicked: self.card_2_rect.center = (563, 585) elif card_3_clicked: self.card_3_rect.center = (715, 593) elif card_4_clicked: self.card_4_rect.center = (862, 591) elif card_5_clicked: self.card_5_rect.center = (1020, 593) self.battle_phase() def _check_cpu_card_clicked(self): """Selects an enemy card randomly and puts it on the field.""" cpu_card_1_clicked = self.cpu_card_1_rect.collidepoint(mouse_pos) cpu_card_2_clicked = self.cpu_card_2_rect.collidepoint(mouse_pos) cpu_card_3_clicked = self.cpu_card_3_rect.collidepoint(mouse_pos) cpu_card_4_clicked = self.cpu_card_4_rect.collidepoint(mouse_pos) cpu_card_5_clicked = self.cpu_card_5_rect.collidepoint(mouse_pos) if cpu_card_1_clicked: # Places the CPU's first card on hand on the board's first spot # if there's no other card there already. self.cpu_card_1_rect.center = (419, 442) elif cpu-card_2_clicked: self.cpu_card_2_rect.center = (570, 444) elif cpu_card_3_clicked: self.cpu_card_3_rect.center = (712, 449) elif cpu_card_4_clicked: self.cpu_card_4_rect.center = (860, 441) elif cpu_card_5_clicked: self.cpu_card_5_rect.center = (1018, 446) def _update_screen(self): """Updates images on the screen and flip to the new screen.""" self.screen.fill(self.settings.bg_color) self.board.blitme() self.deck.blitme() self.cpu_deck.blitme() self.cards.blitme_1() self.cards.blitme_2() self.cards.blitme_3() self.cards.blitme_4() self.cards.blitme_5() self.cpu_cards.blitme_1() self.cpu_cards.blitme_2() self.cpu_cards.blitme_3() self.cpu_cards.blitme_4() self.cpu_cards.blitme_5() if hasattr(self.cards, 'drawn_card_6'): self.cards.blitme_6() if self.cards.rect_6.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_6() if hasattr(self.cpu_cards, 'drawn_card_6'): self.cpu_cards.blitme_6() if self.cpu_cards.rect_6.collidepoint(pygame.mouse.get_pos()): self.cpu_cards.blitme_hover_6() if self.cards.rect_1.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_1() if self.cards.rect_2.collidepoint(pygame.mouse.get_ pos()): self.cards.blitme_hover_2() if self.cards.rect_3.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_3() if self.cards.rect_4.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_4() if self.cards.rect_5.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_5() if self.cpu_cards.rect_1.collidepoint(pygame.mouse.get_pos()): self.cpu_cards.blitme_hover_1() elif self.cpu_cards.rect_2.collidepoint(pygame.mouse.get_pos()): self.cpu_cards.blitme_hover_2() elif self.cpu_cards.rect_3.collidepoint(pygame.mouse.get_pos()): self.cpu_cards.blitme_hover_3() elif self.cpu_cards.rect_4.collidepoint(pygame.mouse.get_pos()): self.cards.blitme_hover_4() elif self.cpu_cards.rect_5.collidepoint(pygame.mouse.get_pos()): self.cpu_cards.blitme_hover_5() # Draw Life Points information. self.lp.show_life_points() pygame.display.flip() if __name__ == '__main__': # Make a game instance, and run the game. cg = CardGame() cg.run_game() and these are the relevant parts of the card.py file, where cards' functionalities are present: import pygame from pygame.sprite import Sprite from settings import Settings import random, os class Card(Sprite): """A class to manage a card.""" def __init__(self, ai_game): """Initialize a card and set its starting position.""" super().__init__() self.screen = ai_game.screen self.screen_rect = ai_game.screen.get_rect() self.deck = [ "starter_deck/abyss_flower.bmp", "starter_deck/acid_crawler.bmp", "starter_deck/acrobat_monkey.bmp", "starter_deck/akakieisu.bmp", "starter_deck/alinsection.bmp", "starter_deck/alligators_sword.bmp", "starter_deck/ancient_brain.bmp", "starter_deck/ancient_elf.bmp", "starter_deck/ancient_jar.bmp", "starter_deck/bickuribox.bmp", "starter_deck/celtic_guardian.bmp", "starter_deck/curse_of_dragon.bmp", "starter_deck/gemini_elf.bmp", "starter_deck/la_jinn.bmp", "starter_deck/skull_knight.bmp" ] # Load the cards' images and get their rects. self.cards = [pygame.image.load(c) for c in self.deck] self.drawn_card_1 = random.choice(self.cards) self.drawn_card_2 = random.choice(self.cards) # This whole while loop section is intended to make sure that we get # 5 distinct cards from one another. while self.drawn_card_1 == self.drawn_card_2: self.drawn_card_2 = random.choice(self.cards) self.drawn_card_3 = random.choice(self.cards) while (self.drawn_card_1 == self.drawn_card_3 or self.drawn_card_2 == self.drawn_card_3): self.drawn_card_3 = random.choice(self.cards) self.drawn_card_4 = random.choice(self.cards) while (self.drawn_card_1 == self.drawn_card_4 or self.drawn_card_2 == self.drawn_card_4 or self.drawn_card_3 == self.drawn_card_4): self.drawn_card_4 = random.choice(self.cards) self.drawn_card_5 = random.choice(self.cards) while (self.drawn_card_1 == self.drawn_card_5 or self.drawn_card_2 == self.drawn_card_5 or self.drawn_card_3 == self.drawn_card_5 or self.drawn_card_4 == self.drawn_card_5): self.drawn_card_5 = random.choice(self.cards) class EnemyCards(Sprite): """A class to manage the CPU's cards.""" ... P.S.: The term 'hover' present in the names of some variables and methods refers to displaying a bigger image of the card while hovering over them with the cursor, but that's not important I guess. Continue reading...