added base config file, it should work but it isn't used yet.

otherwise things are back to normal. minor output updates, removed conspiracies
This commit is contained in:
Bill Zorn 2015-07-06 00:15:12 -07:00
parent eef2e70e28
commit 110ac8473c
4 changed files with 413 additions and 39 deletions

402
config.py Normal file
View File

@ -0,0 +1,402 @@
import re
# Don't be intimidated by the massive size of this file. It provides both the
# raw character decisions made about the encoding scheme as variables, and
# a bunch of tables and functions to make dealing with mana costs and unary
# numbers easier. For the most part the functions should adapt if you change
# the specific delimiters and markers used.
# The decoding from mtgjson format is dependent on the specific structure of
# the internally used mana symbol strings, so if you want to change that you'll
# also have to change the json decoding functions.
# separators
cardsep = '\n\n'
fieldsep = '|'
bsidesep = '\n'
newline = '\\'
# special indicators
dash_marker = '~'
bullet_marker = '='
this_marker = '@'
counter_marker = '%'
reserved_marker = '\r'
x_marker = 'X'
tap_marker = 'T'
untap_marker = 'Q'
# unambiguous synonyms
counter_rename = 'uncast'
# unicode / ascii conversion
unicode_trans = {
u'\u2014' : dash_marker, # unicode long dash
u'\u2022' : bullet_marker, # unicode bullet
u'\u2019' : '"', # single quote
u'\u2018' : '"', # single quote
u'\u2212' : '-', # minus sign
u'\xe6' : 'ae', # ae symbol
u'\xfb' : 'u', # u with caret
u'\xfa' : 'u', # u with accent
u'\xe9' : 'e', # e with accent
u'\xe1' : 'a', # a with accent
u'\xe0' : 'a', # a with accent going the other way
u'\xe2' : 'a', # a with caret
u'\xf6' : 'o', # o with umlaut
u'\xed' : 'i', # i with accent
}
# this one is one-way only
def to_ascii(s):
for uchar in unicode_trans:
s = s.replace(uchar, unicode_trans(uchar))
return s
# unary numbers
unary_marker = '&'
unary_counter = '^'
unary_max = 20
unary_exceptions = {
25 : 'twenty' + dash_marker + 'five',
30 : 'thirty',
40 : 'forty',
50 : 'fifly',
100: 'one hundred',
200: 'two hundred',
}
def to_unary(s, warn = False):
numbers = re.findall(r'[0123456789]+', s)
# replace largest first to avoid accidentally replacing shared substrings
for n in sorted(numbers, cmp = lambda x,y: cmp(int(x), int(y)), reverse = True):
i = int(n)
if i in unary_exceptions:
s = s.replace(n, unary_exceptions[n])
elif i > unary_max:
i = unary_max
if warn:
print s
s = s.replace(n, unary_marker + unary_counter * i)
else:
s = s.replace(n, unary_marker + unary_counter * i)
return s
def from_unary(s):
numbers = re.findall(re.escape(unary_marker + unary_counter) + '*', s)
# again, largest first so we don't replace substrings and break everything
for n in sorted(numbers, cmp = lambda x,y: cmp(len(x), len(y)), reverse = True):
i = (len(n) - len(unary_marker)) / len(unary_counter)
s = s.replace(n, str(i))
return s
# mana syntax
mana_open_delimiter = '{'
mana_close_delimiter = '}'
mana_json_open_delimiter = mana_open_delimiter
mana_json_close_delimiter = mana_close_delimiter
mana_json_hybrid_delimiter = '/'
mana_forum_open_delimiter = '[mana]'
mana_forum_close_delimiter = '[/mana]'
mana_unary_marker = '' # if the same as unary_marker, from_unary WILL replace numbers in mana costs
mana_unary_counter = unary_counter
# individual mana symbols
mana_W = 'W' # single color
mana_U = 'U'
mana_B = 'B'
mana_R = 'R'
mana_G = 'G'
mana_P = 'P' # colorless phyrexian
mana_S = 'S' # snow
mana_X = 'X' # colorless X
mana_WP = 'WP' # single color phyrexian
mana_UP = 'UP'
mana_BP = 'BP'
mana_RP = 'RP'
mana_GP = 'GP'
mana_2W = '2W' # single color hybrid
mana_2U = '2U'
mana_2B = '2B'
mana_2R = '2R'
mana_2G = '2G'
mana_WU = 'WU' # dual color hybrid
mana_WB = 'WB'
mana_RW = 'RW'
mana_GW = 'GW'
mana_UB = 'UB'
mana_UR = 'UR'
mana_GU = 'GU'
mana_BR = 'BR'
mana_BG = 'BG'
mana_RG = 'RG'
# alternative order symbols
mana_WP_alt = 'PW' # single color phyrexian
mana_UP_alt = 'PU'
mana_BP_alt = 'PB'
mana_RP_alt = 'PR'
mana_GP_alt = 'PG'
mana_2W_alt = 'W2' # single color hybrid
mana_2U_alt = 'U2'
mana_2B_alt = 'B2'
mana_2R_alt = 'R2'
mana_2G_alt = 'G2'
mana_WU_alt = 'UW' # dual color hybrid
mana_WB_alt = 'BW'
mana_RW_alt = 'WR'
mana_GW_alt = 'WG'
mana_UB_alt = 'BU'
mana_UR_alt = 'RU'
mana_GU_alt = 'UG'
mana_BR_alt = 'RB'
mana_BG_alt = 'GB'
mana_RG_alt = 'GR'
# special
mana_2 = '2' # use with 'in' to identify single color hybrid
# master symbol lists
mana_syms = [
mana_W,
mana_U,
mana_B,
mana_R,
mana_G,
mana_P,
mana_S,
mana_X,
mana_WP,
mana_UP,
mana_BP,
mana_RP,
mana_GP,
mana_2W,
mana_2U,
mana_2B,
mana_2R,
mana_2G,
mana_WU,
mana_WB,
mana_RW,
mana_GW,
mana_UB,
mana_UR,
mana_GU,
mana_BR,
mana_BG,
mana_RG,
]
mana_symalt = [
mana_WP_alt,
mana_UP_alt,
mana_BP_alt,
mana_RP_alt,
mana_GP_alt,
mana_2W_alt,
mana_2U_alt,
mana_2B_alt,
mana_2R_alt,
mana_2G_alt,
mana_WU_alt,
mana_WB_alt,
mana_RW_alt,
mana_GW_alt,
mana_UB_alt,
mana_UR_alt,
mana_GU_alt,
mana_BR_alt,
mana_BG_alt,
mana_RG_alt,
]
mana_symall = mana_syms + mana_symalt
# alt symbol conversion
def mana_alt(sym):
if not sym in mana_symall:
raise ValueError('invalid mana symbol for mana_alt(): ' + repr(sym))
if len(sym) < 2:
return sym
else:
return sym[::-1]
# produce intended neural net output format
def mana_sym_to_encoding(sym):
if not sym in mana_symall:
raise ValueError('invalid mana symbol for mana_sym_to_encoding(): ' + repr(sym))
if len(sym) < 2:
return sym * 2
else:
return sym
# produce json formatting used in mtgjson
def mana_sym_to_json(sym):
if not sym in mana_symall:
raise ValueError('invalid mana symbol for mana_sym_to_json(): ' + repr(sym))
if len(sym) < 2:
return mana_json_open_delimiter + sym + mana_json_close_delimiter
else:
return (mana_json_open_delimiter + sym[0] + mana_json_hybrid_delimiter
+ sym[1] + mana_json_close_delimiter)
# produce pretty formatting that renders on mtgsalvation forum
# converts individual symbols; surrounding [mana][/mana] tags are added elsewhere
def mana_sym_to_forum(sym):
if not sym in mana_symall:
raise ValueError('invalid mana symbol for mana_sym_to_forum(): ' + repr(sym))
if sym in mana_symalt:
sym = mana_alt(sym)
if len(sym) < 2:
return sym
else:
return mana_json_open_delimiter + sym + mana_json_close_delimiter
# forward symbol tables for encoding
mana_syms_encode = {sym : mana_sym_to_encoding(sym) for sym in mana_syms}
mana_symalt_encode = {sym : mana_sym_to_encoding(sym) for sym in mana_symalt}
mana_symall_encode = {sym : mana_sym_to_encoding(sym) for sym in mana_symall}
mana_syms_jencode = {sym : mana_sym_to_json(sym) for sym in mana_syms}
mana_symalt_jencode = {sym : mana_sym_to_json(sym) for sym in mana_symalt}
mana_symall_jencode = {sym : mana_sym_to_json(sym) for sym in mana_symall}
# reverse symbol tables for decoding
mana_syms_decode = {mana_sym_to_encoding(sym) : sym for sym in mana_syms}
mana_symalt_decode = {mana_sym_to_encoding(sym) : sym for sym in mana_symalt}
mana_symall_decode = {mana_sym_to_encoding(sym) : sym for sym in mana_symall}
mana_syms_jdecode = {mana_sym_to_json(sym) : sym for sym in mana_syms}
mana_symalt_jdecode = {mana_sym_to_json(sym) : sym for sym in mana_symalt}
mana_symall_jdecode = {mana_sym_to_json(sym) : sym for sym in mana_symall}
# going straight from json to encoding and vice versa
def mana_encode_direct(jsym):
if not jsym in mana_symall_jdecode:
raise ValueError('json string not found in decode table for mana_encode_direct(): '
+ repr(jsym))
else:
return mana_symall_encode[mana_symall_jdecode[jsym]]
def mana_decode_direct(sym):
if not sym in mana_symall_decode:
raise ValueError('mana symbol not found in decode table for mana_decode_direct(): '
+ repr(sym))
else:
return mana_symall_jencode[mana_symall_decode[sym]]
# hacked in support for mtgsalvation forum
def mana_decode_direct_forum(sym):
if not sym in mana_symall_decode:
raise ValueError('mana symbol not found in decode table for mana_decode_direct_forum(): '
+ repr(sym))
else:
return mana_sym_to_forum(mana_symall_decode[sym])
# processing entire strings
def unique_string(s):
return ''.join(set(s))
mana_charset_special = mana_unary_marker + mana_unary_counter
mana_charset_strict = unique_string(''.join(mana_symall) + mana_charset_special)
mana_charset = unique_string(mana_charset_strict + mana_charset_strict.lower())
mana_regex_strict = (re.escape(mana_open_delimiter) + '['
+ re.escape(mana_charset_strict)
+ ']*' + re.escape(mana_close_delimiter))
mana_regex = (re.escape(mana_open_delimiter) + '['
+ re.escape(mana_charset)
+ ']*' + re.escape(mana_close_delimiter))
# as a special case, we let unary or decimal numbers exist in json mana strings
mana_jcharset_special = '0123456789' + mana_unary_marker + mana_unary_counter
mana_jcharset_strict = unique_string(''.join(mana_symall_jdecode) + mana_jcharset_special)
mana_jcharset = unique_string(mana_jcharset_strict + mana_jcharset_strict.lower())
# note that json mana strings can't be empty between the delimiters
mana_jregex_strict = (re.escape(mana_json_open_delimiter) + '['
+ re.escape(mana_jcharset_strict)
+ ']+' + re.escape(mana_json_close_delimiter))
mana_jregex = (re.escape(mana_json_open_delimiter) + '['
+ re.escape(mana_jcharset)
+ ']+' + re.escape(mana_json_close_delimiter))
number_decimal_regex = r'[0123456789]+'
number_unary_regex = re.escape(unary_marker) + re.escape(unary_counter) + '*'
mana_decimal_regex = (re.escape(mana_json_open_delimiter) + number_decimal_regex
+ re.escape(mana_json_close_delimiter))
mana_unary_regex = (re.escape(mana_json_open_delimiter) + number_unary_regex
+ re.escape(mana_json_close_delimiter))
# convert a json mana string to the proper encoding
def mana_translate(jmanastr):
manastr = jmanastr
for n in re.findall(mana_unary_regex, manastr):
ns = re.findall(number_unary_regex, n)
i = (len(ns[0]) - len(mana_unary_marker)) / len(mana_unary_counter)
manastr = manastr.replace(n, mana_unary_marker + mana_unary_counter * i)
for n in re.findall(mana_decimal_regex, manastr):
ns = re.findall(number_decimal_regex, n)
i = int(ns[0])
manastr = manastr.replace(n, mana_unary_marker + mana_unary_counter * i)
for jsym in mana_symall_jdecode:
if jsym in manastr:
manastr = manastr.replace(jsym, mana_encode_direct(jsym))
return mana_open_delimiter + manastr + mana_close_delimiter
# convert an encoded mana string back to json
mana_symlen_min = min([len(sym) for sym in mana_symall_decode])
mana_symlen_max = max([len(sym) for sym in mana_symall_decode])
def mana_untranslate(manastr, for_forum = False):
inner = manastr[1:-1]
jmanastr = ''
colorless_total = 0
idx = 0
while idx < len(inner):
# taking this branch is an infinite loop if unary_marker is empty
if len(mana_unary_marker) > 0 and inner[idx:idx+len(mana_unary_marker)] == mana_unary_marker:
idx += len(mana_unary_marker)
elif inner[idx:idx+len(mana_unary_counter)] == mana_unary_counter:
idx += len(mana_unary_counter)
colorless_total += 1
else:
old_idx = idx
for symlen in range(mana_symlen_min, mana_symlen_max + 1):
sym = inner[idx:idx+symlen]
if sym in mana_symall_decode:
idx += symlen
if for_forum:
jmanastr = jmanastr + mana_decode_direct_forum(sym)
else:
jmanastr = jmanastr + mana_decode_direct(sym)
break
# otherwise we'll go into an infinite loop if we see a symbol we don't know
if idx == old_idx:
idx += 1
if for_forum:
if jmanastr == '':
return mana_forum_open_delimiter + str(colorless_total) + mana_forum_close_delimiter
else:
return (mana_forum_open_delimiter + ('' if colorless_total == 0
else str(colorless_total))
+ jmanastr + mana_forum_close_delimiter)
else:
if jmanastr == '':
return mana_json_open_delimiter + str(colorless_total) + mana_json_close_delimiter
else:
return (('' if colorless_total == 0 else
mana_json_open_delimiter + str(colorless_total) + mana_json_close_delimiter)
+ jmanastr)
# finally, replacing all instances in a string
# notice the calls to .upper(), this way we recognize lowercase symbols as well just in case
def to_mana(s):
jmanastrs = re.findall(mana_jregex, s)
for jmanastr in jmanastrs:
s = s.replace(jmanastr, mana_translate(jmanastr.upper()))
return s
def from_mana(s, for_forum = False):
manastrs = re.findall(mana_regex, s)
for manastr in manastrs:
s = s.replace(manastr, mana_untranslate(manastr.upper(), for_forum = for_forum))
return s
# Translation could also be accomplished using the datamine.Manacost object's
# display methods, but these direct string transformations are retained for
# quick scripting and convenience (and used under the hood by that class to
# do its formatting).

View File

@ -9,7 +9,7 @@ valid_encoded_char = r'[abcdefghijklmnopqrstuvwxyz\'+\-*",.:;WUBRGPV/XTQ|\\&^\{\
dash_marker = '~'
bullet_marker = '='
reserved_indicator = '\r'
reserved_marker = '\r'
def to_ascii(s):
s = s.replace(u'\u2014', dash_marker) # unicode long dash
@ -96,7 +96,9 @@ def to_unary(s):
s = s.replace(n, 'two hundred')
else:
if i > unary_max:
# truncate to unary_max
i = unary_max
# warn, because we probably don't want this to happen
print s
s = s.replace(n, unary_marker + unary_counter * i)
@ -135,8 +137,6 @@ def compress_mana(manastring):
'{r/g}' : 'RG',
'{s}' : 'SS',
'{x}' : x_marker * 2,
#'{xx}' : x_marker * 4,
#'{xxx}' : x_marker * 6,
'{t}' : tap_marker,
'{q}' : untap_marker,
}
@ -434,9 +434,9 @@ def rename_uncast(s):
# run only after doing unary conversion
def fix_dashes(s):
s = s.replace('-' + unary_marker, reserved_indicator)
s = s.replace('-' + unary_marker, reserved_marker)
s = s.replace('-', dash_marker)
s = s.replace(reserved_indicator, '-' + unary_marker)
s = s.replace(reserved_marker, '-' + unary_marker)
# level up is annoying
levels = re.findall(r'level &\^*\-&', s)
@ -468,8 +468,6 @@ def fix_x(s):
return s
# run after fixing dashes, it makes the regexes better, but before replacing newlines
def reformat_choice(s):
# the idea is to take 'choose n ~\n=ability\n=ability\n'
@ -537,6 +535,8 @@ def encode(card):
# filter out vanguard cards
if card['layout'] in ['token', 'plane', 'scheme', 'phenomenon', 'vanguard']:
return
if card['type'] in ['Conspiracy']: # just for now?
return
encoding = fieldsep
name = card['name'].lower()
@ -576,9 +576,9 @@ def encode(card):
encoding += fieldsep
# HACK: put the cost again after the text
if 'manaCost' in card:
encoding += replace_mana(card['manaCost'].lower())
encoding += fieldsep
# if 'manaCost' in card:
# encoding += replace_mana(card['manaCost'].lower())
# encoding += fieldsep
# if 'flavor' in card:
# encoding += card['flavor'].lower()

View File

@ -2117,8 +2117,6 @@
|goblin tinkerer||creature||goblin artificer|&^/&^^|{^RR}|{RR}, T: destroy target artifact. that artifact deals damage equal to its converted mana cost to @.|
|unexpected potential||conspiracy|||||hidden agenda \you may spend mana as though it were mana of any color to cast spells with the chosen name.|
|war elemental||creature||elemental|&^/&^|{RRRRRR}|when @ enters the battlefield, sacrifice it unless an opponent was dealt damage this turn.\whenever an opponent is dealt damage, put that many +&^/+&^ counters on @.|
|ensoul artifact||enchantment||aura||{^UU}|enchant artifact\enchanted artifact is a creature with base power and toughness &^^^^^/&^^^^^ in addition to its other types.|
@ -2305,8 +2303,6 @@
|feast of flesh||sorcery||||{BB}|@ deals X damage to target creature and you gain X life, where X is &^ plus the number of cards named @ in all graveyards.|
|secret summoning||conspiracy|||||hidden agenda \whenever a creature with the chosen name enters the battlefield under your control, you may search your library for any number of cards with that name, reveal them, put them into your hand, then shuffle your library.|
|spellshift||instant||||{^^^UU}|uncast target instant or sorcery spell. its controller reveals cards from the top of his or her library until he or she reveals an instant or sorcery card. that player may cast that card without paying its mana cost. then he or she shuffles his or her library.|
|grandmother sengir|legendary|creature||human wizard|&^^^/&^^^|{^^^^BB}|{^BB}, T: target creature gets -&^/-&^ until end of turn.|
@ -4525,8 +4521,6 @@
|pine barrens||land|||||@ enters the battlefield tapped.\T: add {^} to your mana pool.\T: add {BB} or {GG} to your mana pool. @ deals &^ damage to you.|
|double stroke||conspiracy|||||hidden agenda \whenever you cast an instant or sorcery spell with the chosen name, you may copy it. you may choose new targets for the copy.|
|dark betrayal||instant||||{BB}|destroy target black creature.|
|scarred vinebreeder||creature||elf shaman|&^/&^|{^BB}|{^^BB}, exile an elf card from your graveyard: @ gets +&^^^/+&^^^ until end of turn.|
@ -5841,8 +5835,6 @@
|volrath's laboratory||artifact||||{^^^^^}|as @ enters the battlefield, choose a color and a creature type.\{^^^^^}, T: put a &^^/&^^ creature token of the chosen color and type onto the battlefield.|
|muzzio's preparations||conspiracy|||||hidden agenda \each creature you control with the chosen name enters the battlefield with an additional +&^/+&^ counter on it.|
|illumination||instant||||{WWWW}|uncast target artifact or enchantment spell. its controller gains life equal to its converted mana cost.|
|cursed rack||artifact||||{^^^^}|as @ enters the battlefield, choose an opponent.\the chosen player's maximum hand size is four.|
@ -8176,8 +8168,6 @@
|centaur glade||enchantment||||{^^^GGGG}|{^^GGGG}: put a &^^^/&^^^ green centaur creature token onto the battlefield.|
|sultai ascendacy||enchantment||||{UUBBGG}|at the beginning of your upkeep, look at the top two cards of your library. put any number of them into your graveyard and the rest back on top of your library in any order.|
|deathgaze cockatrice||creature||cockatrice|&^^/&^^|{^^BBBB}|flying\deathtouch|
|brimstone dragon||creature||dragon|&^^^^^^/&^^^^^^|{^^^^^^RRRR}|flying, haste|
@ -8452,8 +8442,6 @@
|heroic defiance||enchantment||aura||{^WW}|enchant creature\enchanted creature gets +&^^^/+&^^^ unless it shares a color with the most common color among all permanents or a color tied for most common.|
|worldknit||conspiracy|||||\as long as every card in your card pool started the game in your library or in the command zone, lands you control have "T: add one mana of any color to your mana pool."|
|okiba~gang shinobi||creature||rat ninja|&^^^/&^^|{^^^BBBB}|ninjutsu {^^^BB} \whenever @ deals combat damage to a player, that player discards two cards.|
|rhystic syphon||sorcery||||{^^^BBBB}|unless target player pays {^^^}, he or she loses &^^^^^ life and you gain &^^^^^ life.|
@ -15212,14 +15200,10 @@
|sparkcaster||creature||kavu|&^^^^^/&^^^|{^^RRGG}|when @ enters the battlefield, return a red or green creature you control to its owner's hand.\when @ enters the battlefield, it deals &^ damage to target player.|
|advantageous proclamation||conspiracy|||||\your minimum deck size is reduced by five.|
|precursor golem||artifact creature||golem|&^^^/&^^^|{^^^^^}|when @ enters the battlefield, put two &^^^/&^^^ colorless golem artifact creature tokens onto the battlefield.\whenever a player casts an instant or sorcery spell that targets only a single golem, that player copies that spell for each other golem that spell could target. each copy targets a different one of those golems.|
|sarcomancy||enchantment||||{BB}|when @ enters the battlefield, put a &^^/&^^ black zombie creature token onto the battlefield.\at the beginning of your upkeep, if there are no zombies on the battlefield, @ deals &^ damage to you.|
|iterative analysis||conspiracy|||||hidden agenda \whenever you cast an instant or sorcery spell with the chosen name, you may draw a card.|
|monastery flock||creature||bird|&/&^^^^^|{^^UU}|defender, flying\morph {UU}|
|beck||sorcery||||{GGUU}|whenever a creature enters the battlefield this turn, you may draw a card.\fuse|
@ -15944,8 +15928,6 @@
|chain of vapor||instant||||{UU}|return target nonland permanent to its owner's hand. then that permanent's controller may sacrifice a land. if the player does, he or she may copy this spell and may choose a new target for that copy.|
|secrets of paradise||conspiracy|||||hidden agenda \creatures you control with the chosen name have "T: add one mana of any color to your mana pool."|
|wall of hope||creature||wall|&/&^^^|{WW}|defender \whenever @ is dealt damage, you gain that much life.|
|griffin guide||enchantment||aura||{^^WW}|enchant creature\enchanted creature gets +&^^/+&^^ and has flying.\when enchanted creature dies, put a &^^/&^^ white griffin creature token with flying onto the battlefield.|
@ -20005,8 +19987,6 @@
|ink~treader nephilim||creature||nephilim|&^^^/&^^^|{RRGGWWUU}|whenever a player casts an instant or sorcery spell, if that spell targets only @, copy the spell for each other creature that spell could target. each copy targets a different one of those creatures.|
|sentinel dispatch||conspiracy|||||\at the beginning of the first upkeep, put a &^/&^ colorless construct artifact creature token with defender onto the battlefield.|
|chasm drake||creature||drake|&^^^/&^^^|{^^^^UU}|flying\whenever @ attacks, target creature you control gains flying until end of turn.|
|primitive justice||sorcery||||{^RR}|as an additional cost to cast @, you may pay {^RR} and/or {^GG} any number of times.\destroy target artifact. for each additional {^RR} you paid, destroy another target artifact. for each additional {^GG} you paid, destroy another target artifact, and you gain &^ life.|
@ -22568,8 +22548,6 @@
|myr incubator||artifact||||{^^^^^^}|{^^^^^^}, T, sacrifice @: search your library for any number of artifact cards, exile them, then put that many &^/&^ colorless myr artifact creature tokens onto the battlefield. then shuffle your library.|
|immediate action||conspiracy|||||hidden agenda \creatures you control with the chosen name have haste.|
|distant melody||sorcery||||{^^^UU}|choose a creature type. draw a card for each permanent you control of that type.|
|symbiotic wurm||creature||wurm|&^^^^^^^/&^^^^^^^|{^^^^^GGGGGG}|when @ dies, put seven &^/&^ green insect creature tokens onto the battlefield.|
@ -23859,8 +23837,6 @@
|igneous golem||artifact creature||golem|&^^^/&^^^^|{^^^^^}|{^^}: @ gains trample until end of turn.|
|backup plan||conspiracy|||||\draw an additional hand of seven cards as the game begins. before taking mulligans, shuffle all but one of your hands into your library.|
|cloudcrest lake||land|||||T: add {^} to your mana pool.\T: add {WW} or {UU} to your mana pool. @ doesn't untap during your next untap step.|
|endoskeleton||artifact||||{^^}|you may choose not to untap @ during your untap step.\{^^}, T: target creature gets +&/+&^^^ for as long as @ remains tapped.|
@ -26072,8 +26048,6 @@
|crumbling colossus||artifact creature||golem|&^^^^^^^/&^^^^|{^^^^^}|trample \when @ attacks, sacrifice it at end of combat.|
|brago's favor||conspiracy|||||hidden agenda \spells with the chosen name you cast cost {^} less to cast.|
|caustic hound||creature||hound|&^^^^/&^^^^|{^^^^^BB}|when @ dies, each player loses &^^^^ life.|
|eldrazi conscription||tribal enchantment||eldrazi aura||{^^^^^^^^}|enchant creature\enchanted creature gets +&^^^^^^^^^^/+&^^^^^^^^^^ and has trample and annihilator &^^.|
@ -29179,8 +29153,6 @@
|ruination||sorcery||||{^^^RR}|destroy all nonbasic lands.|
|power play||conspiracy|||||\you are the starting player. if multiple players would be the starting player, one of those players is chosen at random.|
|fresh volunteers||creature||human rebel|&^^/&^^|{^WW}||
|stormsurge kraken||creature||kraken|&^^^^^/&^^^^^|{^^^UUUU}|hexproof\lieutenant ~ as long as you control your commander, @ gets +&^^/+&^^ and has "whenever @ becomes blocked, you may draw two cards."|

View File

@ -6,7 +6,7 @@ import sys
def from_unary(s):
numbers = re.findall(r'&\^*', s)
for number in sorted(numbers, cmp = lambda x,y: cmp(len(x), len(y)) * -1):
for number in sorted(numbers, cmp = lambda x,y: cmp(len(x), len(y)), reverse = True):
i = len(number) - 1
s = s.replace(number, str(i))
return s