import sys import math from mtg import * import database def combinations(total, n): return math.factorial(total) / (math.factorial(n) * math.factorial(total - n)) def h(n, z, x, y): return (combinations(x, n) * combinations(y - x, z - n)) / float(combinations(y, z)) def draw_probability(available, deck, count=1, turn=1, used=0): if count == 0: return h(0, 7 + turn - 1 - used, available, len(deck)) total = sum([h(n, 7 + turn - 1 - used, available, len(deck)) for n in range(count)]) return 1 - total def graph(data, title, hideEmpty=True): categories = sorted(data.keys()) cjust = sorted([len(str(k)) for k in data.keys()]).pop() vjust = sorted([len(str(v)) for v in data.values()]).pop() max = sorted(data.values()).pop() print title print '-' * 80 for category in categories: if hideEmpty and not data[category]: continue heading = str(category).ljust(cjust) value = str(data[category]).rjust(vjust) bar = '*' * int(data[category] * (80 - cjust - vjust - 6) / float(max)) print '{0} [{1}] | {2}'.format(heading, value, bar) if hideEmpty and not max: print ' *** Nothing to display ***' def mana_curve(deck): costs = [c.cost.converted() for c in deck if c.cost.converted() > 0] data = {} for i in range(1, sorted(costs).pop() + 1): data[i] = 0 for c in costs: data[c] += 1 return data def rampup(deck, type=None): print '{0} Rampup'.format((type if type else 'spell').title()) print '-' * 80 land = [c for c in deck if 'land' in c.type.split(' ')] cards = [c for c in deck if c.cost.converted() > 0] if type: cards = [c for c in cards if type in c.type.split(' ')] avgCost = sum([c.cost.converted() for c in cards]) / float(len(cards)) maxCost = sorted([c.cost.converted() for c in cards]).pop() print 'Average {0} cost: {1:.3f}'.format(type if type else 'spell', avgCost) avgCost = int(round(avgCost)) for turn in range(avgCost, maxCost + 1): castable = [c for c in cards if c.cost.converted() <= turn] pm = 1 - draw_probability(len(land), deck, avgCost, turn) pc = 1 - draw_probability(len(castable), deck, 1, turn, avgCost) p = 1 - pm - pc print 'Probability of drawing {0} mana in {1} turns with a castable {3}: {2:.3f}'.format(avgCost, turn, p * 100, type if type else 'spell') def types(deck): return { 'Lands': len([c for c in deck if 'land' in c.type.split(' ')]), 'Creatures': len([c for c in deck if 'creature' in c.type.split(' ')]), 'Artifacts': len([c for c in deck if 'artifact' in c.type.split(' ')]), 'Enchantments': len([c for c in deck if 'enchantment' in c.type.split(' ')]), 'Sorceries': len([c for c in deck if 'sorcery' in c.type.split(' ')]), 'Instants': len([c for c in deck if 'instant' in c.type.split(' ')]), } def colors(deck): data = {} for color in Mana.types.values(): data[color] = 0 for card in deck: if 'land' in card.type.split(' '): if 'swamp' in card.attributes: data[Mana.types['B']] += 1 if 'island' in card.attributes: data[Mana.types['U']] += 1 if 'mountain' in card.attributes: data[Mana.types['R']] += 1 if 'forest' in card.attributes: data[Mana.types['G']] += 1 if 'plains' in card.attributes: data[Mana.types['W']] += 1 else: for color, value in card.cost.mana.mana.iteritems(): data[Mana.types[color]] += 1 if value > 0 else 0 return data def rarities(deck): data = {} for rarity in Card.rarities.values(): data[rarity] = 0 for card in deck: if not card.rarity: continue data[Card.rarities[card.rarity]] += 1 return data if __name__ == '__main__': db = database.TextDB('db.txt') if len(sys.argv) < 2: print 'No decks specified.' sys.exit(1) for filename in sys.argv[1:]: print 'Loading deck in "{0}"...'.format(filename) deck = Deck() """ with open(filename, 'r') as f: for line in f: line = line.strip() if not re.match('^\d+ .+$', line): continue line = line.split(' ') count = int(line.pop(0)) name = ' '.join(line) card = db.getCard(name) if not card: print 'Invalid card: ', name continue deck.extend(card * count) """ deck.load(filename, db) print 'Loaded', len(deck), 'cards.' graph(mana_curve(deck), '\nMana Curve', hideEmpty=False) graph(types(deck), '\nCard Types') graph(colors(deck), '\nColors') graph(rarities(deck), '\nRarities') print rampup(deck) print rampup(deck, 'creature');