2010-06-30 06:23:32 +00:00
|
|
|
import sys
|
2010-06-30 18:42:18 +00:00
|
|
|
import math
|
2010-06-30 06:23:32 +00:00
|
|
|
from mtg import *
|
|
|
|
import database
|
|
|
|
|
2010-06-30 18:42:18 +00:00
|
|
|
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:
|
2010-09-23 01:24:53 +00:00
|
|
|
return h(0, 7 + turn - 1 - used, available, deck)
|
|
|
|
total = sum([h(n, 7 + turn - 1 - used, available, deck) for n in range(count)])
|
2010-06-30 18:42:18 +00:00
|
|
|
return 1 - total
|
|
|
|
|
2010-06-30 06:23:32 +00:00
|
|
|
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
|
2010-06-30 19:30:55 +00:00
|
|
|
|
|
|
|
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]
|
2010-09-23 01:24:53 +00:00
|
|
|
pm = 1 - draw_probability(len(land), len(deck), avgCost, turn)
|
|
|
|
pc = 1 - draw_probability(len(castable), len(deck), 1, turn, avgCost)
|
2010-06-30 19:30:55 +00:00
|
|
|
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')
|
2010-06-30 06:23:32 +00:00
|
|
|
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
|
2010-06-30 11:52:01 +00:00
|
|
|
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
|
2010-06-30 06:23:32 +00:00
|
|
|
|
2010-06-30 18:42:18 +00:00
|
|
|
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')
|
2010-06-30 19:30:55 +00:00
|
|
|
|
|
|
|
print
|
|
|
|
rampup(deck)
|
|
|
|
print
|
|
|
|
rampup(deck, 'creature');
|