172 lines
5.4 KiB
Python
172 lines
5.4 KiB
Python
import copy
|
|
import random
|
|
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 = self.any + other.any
|
|
result.mana = self.mana + other.mana
|
|
return result
|
|
def __sub__(self, other):
|
|
result = ManaCost()
|
|
if isinstance(other, ManaCost):
|
|
result.any = self.any - other.any
|
|
result.mana = self.mana - other.mana
|
|
return result
|
|
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
|