import copy import random import cards from observable import Observable class Game: def __init__(self): self.players = [] class Mana: types = { 'W': 'White', 'U': 'Blue', 'B': 'Black', 'R': 'Red', 'G': 'Green', } def __init__(self, mana=None): self.mana = {} for type in Mana.types.keys(): self.mana[type] = 0 if mana: # Can't just set self to result... ? result = self + mana self.mana = result.mana def __add__(self, other): result = Mana() if isinstance(other, str): for m in [c for c in other.upper() if c in Mana.types.keys()]: result.mana[m] = result.mana[m] + 1 elif isinstance(other,Mana): for (key, value) in other.mana.iteritems(): result.mana[key] = self.mana[key] + value else: # TODO: raise exception raise Exception() pass return result def __sub__(self, other): result = Mana() if isinstance(other, Mana): for (key, value) in other.mana.iteritems(): result.mana[key] = self.mana[key] - value if result.mana[key] < 0: raise Exception('Insufficient {0} Mana'.format(Mana.types[key])) elif isinstance(other,ManaCost): for (key, value) in other.mana.mana.iteritems(): result.mana[key] = self.mana[key] - value if result.mana[key] < 0: raise Exception('Insufficient {0} Mana'.format(Mana.types[key])) remaining = other.any for (key, value) in result.mana.iteritems(): while result.mana[key] > 0 and remaining > 0: result.mana[key] = result.mana[key] - 1 remaining = remaining - 1 if remaining > 0: raise Exception('Insufficient Mana') return result def __repr__(self): return ''.join([type * count for (type, count) in self.mana.iteritems()]) if self.converted() > 0 else '0' def converted(self): return sum(self.mana.values()) class ManaCost: def __init__(self, cost=None): self.any = 0 self.mana = Mana() if cost: result = self + cost self.any = result.any self.mana = result.mana def __add__(self, other): result = ManaCost() if isinstance(other, str): result.mana = Mana(other) value = '' for c in other: if c not in '0123456789': break value = value + c value = int(value) if len(value) > 0 else 0 result.any = value elif isinstance(other, Mana): result.mana = other elif isinstance(other, ManaCost): result.any = other.many result.mana = other.many return result def __sub__(self, other): if isinstance(other, ManaCost): result.any = self.any - right.any result.mana = self.mana - right.mana def __repr__(self): return '{0}{1}'.format( self.any if self.any > 0 or self.mana.converted() == 0 else '', self.mana if self.mana.converted() > 0 else '' ) def converted(self): return self.mana.converted() + self.any class Player: def __init__(self, name, deck=None): self.name = name self.deck = None self.setDeck(deck) self.hand = CardList() self.graveyard = CardList() self.battlefield = CardList() def __repr__(self): return 'Player: {0} [Deck:{1}]'.format(self.name, len(self.deck)) def setDeck(self, deck): if not deck: return self.deck = copy.copy(deck) for card in deck: card.owner = self def draw(self): card = self.deck.pop() self.hand.append(card) card.moved.emit('deck', 'hand') def cast(self, card): hand.remove(card) self.battlefield.append(card) card.moved.emit('hand', 'battlefield') class Card: def __init__(self, name, attributes, cost, power, toughness, owner=None): self.name = name self.attributes = [a.lower() for a in attributes] self.cost = cost self.power = power self.toughness = toughness self.owner = owner # Events self.moved = Observable() self.tapped = Observable() self.attacked = Observable() self.store() def __repr__(self): return 'Card: [{2}] {0}: {1} [{3}/{4}]'.format(self.name, ' '.join([a.capitalize() for a in self.attributes]), self.cost, self.power, self.toughness) def store(self): self.__stored = copy.copy(self) def restore(self): self = copy.copy(self.__stored) def tap(self): self.tapped.emit() class Ability: def __init__(self, target): self.target = target self.init() def init(self): pass class CardList(list): def __init__(self, game): list.__init__(self) self.game = game def append(self, item): item.list = self list.append(self, item) class Deck(CardList): def __init__(self): pass def shuffle(self): random.shuffle(self) def cards(self): return self.__cards