mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
6a615bb47e
Big keyword update. Update to allow new flip card technology. Update to allow 4-ability planeswalkers, textless lands, and levelers. More statistics that are related to card type. Custom subtype tracking for all card types. Planeswalker types included. Creature type updates. New symbol variation for set symbol watermarks; more like what appears on real cards. Updated card sorting. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1494 0fc631ac-6414-0410-93d0-97cfa31319b6
633 lines
24 KiB
Plaintext
633 lines
24 KiB
Plaintext
############################################################## Localization
|
||
|
||
include file: language
|
||
|
||
############################################################## Sorting mana symbols
|
||
|
||
# correctly sort a mana symbol (no guild mana)
|
||
mana_sort := sort_text@(order: "XYZI[0123456789]S(WUBRG)")
|
||
# correctly sort guild mana
|
||
mana_sort_guild := sort_text@(order: "[XYZI01234567890SWUBRG/|]") +
|
||
replace@(
|
||
# No lookbehind :(
|
||
#match: "(?<!/)(./.|././.|./././.|.[|])(?!/)",
|
||
match: "./.|././.|./././.|.[|]",
|
||
in_context: "(^|[^/])<match>($|[^/])",
|
||
replace: {sort_text(order:"in_place((WUBRG)")}
|
||
)
|
||
mana_has_guild := match@(match: "[/|]") # Is there guild or half mana in the input?
|
||
# A mana cost can contain both normal and guild mana
|
||
mana_filter := to_upper + {
|
||
if mana_has_guild() then mana_sort_guild()
|
||
else mana_sort()
|
||
}
|
||
# Like mana filter, only also allow tap symbols:
|
||
tap_filter := sort_text@(order: "<CTQ>")
|
||
mana_filter_t := replace@( # Remove [] used for forcing mana symbols
|
||
match: "[\\[\\]]",
|
||
replace: ""
|
||
) + { tap_filter() + mana_filter() }
|
||
|
||
|
||
############################################################## Determine card color
|
||
|
||
# Names of colors
|
||
color_name := {
|
||
if input = "W" then "white"
|
||
else if input = "U" then "blue"
|
||
else if input = "B" then "black"
|
||
else if input = "R" then "red"
|
||
else if input = "G" then "green"
|
||
else ""
|
||
}
|
||
color_names_1 := { color_name(colors.0) }
|
||
color_names_2 := { color_name(colors.0) + ", " + color_name(colors.1) }
|
||
color_names_3 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) }
|
||
color_names_4 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) }
|
||
color_names_5 := { color_name(colors.0) + ", " + color_name(colors.1) + ", " + color_name(colors.2) + ", " + color_name(colors.3) + ", " + color_name(colors.4) }
|
||
# color based on mana cost, input = a mana cost
|
||
color_filter := sort_text@(order: "<WUBRG>")
|
||
color_filterH := sort_text@(order: "</>")
|
||
mana_to_color := {
|
||
count := number_of_items(in: colors)
|
||
if hybrid == "" and contains(type, match:"Artifact") then
|
||
# not a hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if set.set_info.use_gradient_multicolor == "no" then "artifact, multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", artifact, multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "artifact, multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", artifact, multicolor"
|
||
else if count == 4 then color_names_4() + ", artifact, multicolor"
|
||
else if count == 5 then color_names_5() + ", artifact, multicolor"
|
||
else "artifact, multicolor"
|
||
else if hybrid == "" then
|
||
# not a hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if set.set_info.use_gradient_multicolor == "no" then "multicolor" # stop here
|
||
else if count == 2 then color_names_2() + ", multicolor"
|
||
else if set.set_info.use_gradient_multicolor != "yes" then "multicolor" # stop here
|
||
else if count == 3 then color_names_3() + ", multicolor"
|
||
else if count == 4 then color_names_4() + ", multicolor"
|
||
else if count == 5 then color_names_5() + ", multicolor"
|
||
else "multicolor"
|
||
else if contains(type, match:"Artifact") then
|
||
# hybrid, but artifact
|
||
if count == 0 then "artifact"
|
||
else if count == 1 then color_names_1() + ", artifact"
|
||
else if count == 2 then color_names_2() + ", artifact"
|
||
else "artifact, multicolor"
|
||
else
|
||
# hybrid, not artifact
|
||
if count == 0 then "colorless"
|
||
else if count == 1 then color_names_1()
|
||
else if count == 2 then color_names_2() + ", hybrid"
|
||
else "multicolor"
|
||
}
|
||
|
||
# color based on land text box, input = textbox contents
|
||
color_text_filter :=
|
||
# remove activation costs
|
||
replace@(
|
||
match: "<sym[^>]*>[^<]+</sym[^>]*>"
|
||
in_context: "(?ix) (\\n|^)[^:]*<match>(,|:) | (pays?|additional|costs?)[ ]<match>",
|
||
replace: ""
|
||
) +
|
||
# keep only mana
|
||
filter_text@(match: "<sym[^>]*>([^<]+)") + color_filter;
|
||
# get the land frame for a "WUBRG"-style input.
|
||
land_multicolor := {
|
||
count := number_of_items(in: colors)
|
||
if count == 0 then "land"
|
||
else if count == 1 then color_names_1() + ", land"
|
||
else if count == 2 then color_names_2() + ", land"
|
||
else "land, multicolor"
|
||
}
|
||
land_to_color := {
|
||
# Based on watermark
|
||
if watermark = "mana symbol white" then "white, land"
|
||
else if watermark = "mana symbol blue" then "blue, land"
|
||
else if watermark = "mana symbol black" then "black, land"
|
||
else if watermark = "mana symbol red" then "red, land"
|
||
else if watermark = "mana symbol green" then "green, land"
|
||
else land_multicolor(colors:color_text_filter(input: card.rule_text))
|
||
};
|
||
|
||
# Look for a CDA that defines colors
|
||
text_to_color := {
|
||
# Note: running filter_text is quite slow, do a quick 'contains' check first
|
||
if contains(match: card_name) then (
|
||
text := filter_text(match: "is (colorless|all colors|((blue|white|green|red|black)((,|,? and) (blue|white|green|red|black))*))", in_context: regex_escape(card_name)+"(</[-a-z]+>)* <match>\\.")
|
||
if text != "" then (
|
||
if contains(text, match: "all colors") then (
|
||
colors := "WUBRG"
|
||
if land = "land" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
) else (
|
||
colors := ""
|
||
if contains(text, match: "white") then colors := colors + "W"
|
||
if contains(text, match: "blue") then colors := colors + "U"
|
||
if contains(text, match: "black") then colors := colors + "B"
|
||
if contains(text, match: "red") then colors := colors + "R"
|
||
if contains(text, match: "green") then colors := colors + "G"
|
||
if land = "land" then land_multicolor()
|
||
else mana_to_color(hybrid: "")
|
||
)
|
||
)
|
||
)
|
||
}
|
||
|
||
# The color of a card
|
||
is_creature := match@(match: "(?i)Creature")
|
||
is_tribal := match@(match: "(?i)Tribal")
|
||
is_artifact := match@(match: "(?i)Artifact")
|
||
is_land := match@(match: "(?i)Land")
|
||
is_enchantment := match@(match: "(?i)Enchantment")
|
||
is_spell := match@(match: "(?i)Instant|Sorcery")
|
||
card_color := {
|
||
# usually the color of mana
|
||
text_color := text_to_color(rules_text, land: is_land(type));
|
||
if text_color == "" then (
|
||
mana_color := mana_to_color(colors: color_filter(casting_cost), hybrid: color_filterH(casting_cost))
|
||
if mana_color == "colorless" and is_land (type) then land_to_color(watermark)
|
||
else if mana_color == "colorless" and is_artifact(type) then "artifact"
|
||
else if mana_color == "colorless" and contains(card.shape, match:"flip") then default
|
||
else mana_color
|
||
)
|
||
else text_color
|
||
};
|
||
|
||
# Number of colors in a card_color
|
||
card_color_color_count := count_chosen@(choices: "white,blue,black,red,green,artifact")
|
||
# Clean up color field
|
||
card_color_filter := {
|
||
colors := card_color_color_count()
|
||
if colors > 2 then
|
||
input := remove_choice(choice: "overlay")
|
||
if colors > 1 then (
|
||
input := require_choice(choices: "multicolor, hybrid, land, artifact")
|
||
input := exclusive_choice(choices: "multicolor, hybrid")
|
||
input := require_exclusive_choice(choices: "horizontal, vertical, radial, overlay")
|
||
) else
|
||
input := remove_choice(choices: "radial, horizontal, vertical, overlay, hybrid, reversed")
|
||
if chosen(choice:"overlay") then
|
||
input := remove_choice(choice: "reversed")
|
||
input
|
||
}
|
||
|
||
# needed by all style files anyway
|
||
include file: /magic-blends.mse-include/new-blends
|
||
|
||
|
||
############################################################## Card number
|
||
|
||
# Index for sorting, white cards are first, so white->A, blue->B, .. ,
|
||
# The code consists of 3 parts:
|
||
# color, shifted, split
|
||
sort_index := {
|
||
color_of_card() +
|
||
(if contains(card.shape, match:"shifted") then "S" else " ") + # planeshifted cards come after normal ones
|
||
(if contains(card.shape, match:"split") then "S" else " ") + # split cards come after normal ones
|
||
":"
|
||
}
|
||
# Process the name for sorting rules
|
||
sort_name :=
|
||
# Remove "The", "A", and "And" at the beginning
|
||
replace@(match: "^(The|An?) ", replace: "") +
|
||
# Remove commas and apostrophes
|
||
replace@(match: "(,|'|’)", replace: "") +
|
||
# Remove bold and italic tags
|
||
replace@(match: "(<b>|<i>|</b>|</i>)", replace: "") +
|
||
# Make lowercase
|
||
to_lower
|
||
|
||
is_multicolor := { chosen(choice: "multicolor") and input != "artifact, multicolor" }
|
||
is_null_cost := { input == "" or input == "0" }
|
||
is_hybrid_cost := { contains(card.casting_cost, match: "W/") or contains(card.casting_cost, match: "U/") or contains(card.casting_cost, match: "B/") or contains(card.casting_cost, match: "R/") or contains(card.casting_cost, match: "G/") }
|
||
basic_land_sort := {
|
||
if contains(card.name, match:"Plains") then "MB" # Plains
|
||
else if contains(card.name, match:"Island") then "MC" # Islands
|
||
else if contains(card.name, match:"Swamp") then "MD" # Swamps
|
||
else if contains(card.name, match:"Mountain") then "ME" # Mountains
|
||
else if contains(card.name, match:"Forest") then "MF" # Forests
|
||
else "MA" # other basic lands
|
||
}
|
||
hybrid_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if colors = "WU" then "HA"
|
||
else if colors = "UB" then "HB"
|
||
else if colors = "BR" then "HC"
|
||
else if colors = "RG" then "HD"
|
||
else if colors = "WG" then "HE"
|
||
else if colors = "WB" then "HF"
|
||
else if colors = "UR" then "HG"
|
||
else if colors = "BG" then "HH"
|
||
else if colors = "WR" then "HI"
|
||
else if colors = "UG" then "HJ"
|
||
else "HK"
|
||
}
|
||
multi_color_pair_sort := {
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if colors = "WU" then "GA"
|
||
else if colors = "UB" then "GB"
|
||
else if colors = "BR" then "GC"
|
||
else if colors = "RG" then "GD"
|
||
else if colors = "WG" then "GE"
|
||
else if colors = "WB" then "GF"
|
||
else if colors = "UR" then "GG"
|
||
else if colors = "BG" then "GH"
|
||
else if colors = "WR" then "GI"
|
||
else if colors = "UG" then "GJ"
|
||
else if contains(card.casting_cost, match:"/") then "GL"
|
||
else "GK"
|
||
}
|
||
# A code for the color of the card
|
||
color_of_card := {
|
||
card_color := card.card_color
|
||
casting_cost := card.casting_cost
|
||
type := card.super_type
|
||
if card.shape == "split" and
|
||
card_color != card.card_color_2 then "I" # Diff Color Splits
|
||
else if chosen(choice: "land", card_color) then ( # Lands
|
||
if card.rarity != "basic land" then "L" # Nonbasic Land
|
||
else basic_land_sort() # Basic Land
|
||
) else if is_null_cost(casting_cost) then ( # Non-Land Cards with no or zero costs.
|
||
if chosen(choice: "colorless", card_color) then "A" # Clear Colorless
|
||
else if chosen(choice: "hybrid", card_color) then "HK" # Hybrids
|
||
else if is_multicolor(card_color) then "GK" # Multicolor
|
||
else if chosen(choice:"white", card_color) then "B" # White
|
||
else if chosen(choice:"blue", card_color) then "C" # Blue
|
||
else if chosen(choice:"black", card_color) then "D" # Black
|
||
else if chosen(choice:"red", card_color) then "E" # Red
|
||
else if chosen(choice:"green", card_color) then "F" # Green
|
||
else "J" # Artifact
|
||
) else (
|
||
# Cards with costs.
|
||
colors := sort_text(casting_cost, order: "<WUBRG>")
|
||
if colors == "" and contains(type, match:"Artifact") then "J" # Artifact
|
||
else if colors == "" then "A" # Clear Colorless
|
||
else if colors == "W" then "B" # White
|
||
else if colors == "U" then "C" # Blue
|
||
else if colors == "B" then "D" # Black
|
||
else if colors == "R" then "E" # Red
|
||
else if colors == "G" then "F" # Green
|
||
else if is_hybrid_cost() then hybrid_color_pair_sort() # Hybrid (by pairs)
|
||
else if contains(casting_cost, match:"/") and contains(type, match:"Artifact") then "I" # Hybrid Artifacts
|
||
else multi_color_pair_sort() # Multicolor (by pairs)
|
||
)
|
||
}
|
||
|
||
rarity_sort := {
|
||
if card.shape == "token" then "T"
|
||
else if card.shape == "rulestip" then "U"
|
||
else if set.sort_special_rarity == "with the rest" or card.rarity != "special" then " "
|
||
else "S"
|
||
}
|
||
set_filter := {
|
||
# TODO: what about rulestips?
|
||
if card.shape == "token" then
|
||
{ card.shape == "token" }
|
||
else if card.shape == "rulestip" then
|
||
{ card.shape == "rulestip" }
|
||
else if set.sort_special_rarity != "separate numbering" then
|
||
{ card.shape != "token" and card.shape != "rulestip" }
|
||
else if card.rarity == "special" then
|
||
{ card.shape != "token" and card.shape != "rulestip" and card.rarity == "special" }
|
||
else
|
||
{ card.shape != "token" and card.shape != "rulestip" and card.rarity != "special" }
|
||
}
|
||
|
||
card_number := {
|
||
position (
|
||
of: card
|
||
in: set
|
||
order_by: { rarity_sort() + sort_index() + sort_name(card.name) }
|
||
filter: set_filter()
|
||
) + 1
|
||
}
|
||
card_count := {
|
||
number_of_items(in: set, filter: set_filter())
|
||
}
|
||
|
||
# used by pack scripts
|
||
is_token_card := { card.shape == "token" or card.shape == "rulestip" }
|
||
is_shifted_card := { contains(card.shape, match:"shifted") }
|
||
|
||
|
||
############################################################## Utilities for keywords
|
||
|
||
# Replace spaces by a spacer
|
||
separate_words := remove_tags + trim + replace@(match:" ", replace: {spacer})
|
||
|
||
# replaces — correctly
|
||
add := "" # default is nothing
|
||
# If the 'input' parameter is a mana costs, then adds 'add'
|
||
for_mana_costs := format_cost := {
|
||
if input.separator_before == "—" and contains(input.param, match: " ") then (
|
||
if contains(input.param, match:",") then (
|
||
if match(match: "^[SCTQXYZIWUBRG0-9/|]+,", input.param) then
|
||
"{add}<param-cost>{combined_cost(input.param)}</param-cost>"
|
||
else "<param-cost>{combined_cost(input.param)}</param-cost>"
|
||
) else
|
||
"<param-cost>{alternative_cost(input.param)}</param-cost>"
|
||
) else
|
||
"{add}<param-mana>{input.param}</param-mana>"
|
||
}
|
||
# Convert first character to lower case
|
||
alternative_cost := replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
#
|
||
combined_cost := replace@(match:", [A-Z]", replace: { to_lower() })+
|
||
replace@(match:",", replace:" and")+
|
||
replace@(match:"^[SCTQXYZIWUBRG0-9/|]", in_context: "(^|[[:space:]])<match>", replace: "<sym-auto>&</sym-auto>")+
|
||
replace@(match:"^[A-Z]", replace: { to_lower() })
|
||
long_dash := replace@(match:"-", replace:"—")
|
||
|
||
# Utilities for keywords
|
||
has_cc := { card.casting_cost != "" }
|
||
has_pt := { card.pt != "" }
|
||
|
||
contains_target := match@(match:"(?i)([^a-z]|^)target([^a-z]|$)")
|
||
is_targeted := { contains_target(card.rule_text) }
|
||
|
||
|
||
############################################################## The text box
|
||
|
||
# Filters for the text box
|
||
# context in which mana symbols are found
|
||
mana_context :=
|
||
"(?ix) # case insensitive, ignore whitespace
|
||
(^|[[:space:]\"(“']) # start of a word
|
||
( <match>: # G: something
|
||
| <match>, # G, tap: something
|
||
| <match>[ ]can[ ]be[ ]pay
|
||
| (pays?|additional|costs?|the # pay X. creatures cost 1 less. pay an additional G.
|
||
|adds?|pay(ed)?[ ](with|using)
|
||
)
|
||
([ ]either)? # pay either X or Y
|
||
([ ](<sym[^>]*>)?[SCTQXYZIWUBRG0-9/|]+(</sym[^>]*>)?,)* # pay X, Y or Z
|
||
([ ](<sym[^>]*>)?[SCTQXYZIWUBRG0-9/|]+(</sym[^>]*>)?[ ](and|or|and/or))* # pay X or Y
|
||
[ ]<match>
|
||
([,.)]|$ # (end of word)
|
||
|[ ][^ .,]*$ # still typing...
|
||
|[ ]( or | and | in | less | more | to ) # or next word is ...
|
||
)
|
||
)
|
||
| <param-mana><match></param-mana> # keyword argument that is declared as mana
|
||
| <param-cost>[ ]*<match></param-cost> # keyword argument that is declared as cost
|
||
| <param-cost><match>, # keyword argument that is declared as cost
|
||
";
|
||
|
||
# truncates the name of legends
|
||
legend_filter := replace@(match:"(, | of | the ).*", replace: "" )
|
||
|
||
# these are considered a correct 'word' for spellchecking in the text box:
|
||
additional_text_words := match@(match:
|
||
"(?ix)^(?: # match whole word
|
||
<atom-[^>]*>.*?</atom-[^>]*> # cardnames and stuff
|
||
| [+-]?[0-9X]+ / [+-]?[0-9X]+ # '3/3', '+X/+X'
|
||
)$")
|
||
|
||
# the rule text filter
|
||
# - adds mana symbols
|
||
# - makes text in parentheses italic
|
||
text_filter :=
|
||
# step 1 : remove all automatic tags
|
||
remove_tag@(tag: "<sym-auto>") +
|
||
remove_tag@(tag: "<i-auto>") +
|
||
remove_tag@(tag: "<b-auto>") +
|
||
remove_tag@(tag: "<error-spelling") +
|
||
remove_tag@(tag: "<nospellcheck") +
|
||
# step 2 : reminder text for keywords
|
||
expand_keywords@(
|
||
condition: {
|
||
correct_case or (mode != "pseudo" and not used_placeholders)
|
||
}
|
||
default_expand: {
|
||
chosen(choice:if correct_case then mode else "lower case", set.automatic_reminder_text)
|
||
},
|
||
combine: {
|
||
keyword := "<nospellcheck>{keyword}</nospellcheck>"
|
||
reminder := process_english_hints(reminder)
|
||
if mode == "pseudo" then "<i-auto>{keyword}</i-auto>"
|
||
else keyword + if expand then "<atom-reminder-{mode}> ({reminder})</atom-reminder-{mode}>"
|
||
}) +
|
||
# step 2b : move action keywords' reminder text to the end of the line
|
||
replace@(
|
||
match: "(<atom-reminder-action>(?:(?!<kw-).)*</atom-reminder-action></kw[^>]*>)(((?!<atom-reminder| ?<kw-)[^\n(])+)",
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 2c : remove duplicate reminder text
|
||
replace@(
|
||
match: "(<atom-reminder-[^>]*>[^)]+[)]</atom-reminder-[^>]*>)([^\n]+)\\1"
|
||
replace: "\\2\\1"
|
||
) +
|
||
# step 3a : expand shortcut word CARDNAME
|
||
replace@(
|
||
match: "CARDNAME",
|
||
in_context: "(^|[[:space:]]|\\()<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-cardname></atom-cardname>"
|
||
) +
|
||
# step 3b : expand shortcut word LEGENDNAME
|
||
replace@(
|
||
match: "LEGENDNAME",
|
||
in_context: "(^|[[:space:]]|\\()<match>", # TODO: Allow any punctuation before
|
||
replace: "<atom-legname></atom-legname>"
|
||
) +
|
||
# step 3c : fill in atom fields
|
||
tag_contents@(
|
||
tag: "<atom-cardname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "CARDNAME" else card_name) + "</nospellcheck>" }
|
||
) +
|
||
tag_contents@(
|
||
tag: "<atom-legname>",
|
||
contents: { "<nospellcheck>" + (if card_name=="" then "LEGENDNAME" else legend_filter(card_name)) + "</nospellcheck>" }
|
||
) +
|
||
# step 4 : explict non mana symbols
|
||
replace@(
|
||
match: "\\][SCTQXYZIWUBRG0-9/|]+\\[",
|
||
replace: {"<nosym>" + mana_filter_t() + "</nosym>"} ) +
|
||
# step 5 : add mana & tap symbols
|
||
replace@(
|
||
match: "\\b[SCTQXYZIWUBRG0-9/|]+\\b",
|
||
in_context: mana_context,
|
||
replace: {"<sym-auto>" + mana_filter_t() + "</sym-auto>"} ) +
|
||
# step 5b : add explict mana symbols
|
||
replace@(
|
||
match: "\\[[SCTQXYZIWUBRG0-9/|]+\\]",
|
||
replace: {"<sym>" + mana_filter_t() + "</sym>"} ) +
|
||
# step 6 : curly quotes
|
||
curly_quotes +
|
||
# step 7 : italicize text in parenthesis
|
||
replace@(
|
||
match: "[(]([^)\n]|[(][^)\n]*[)])*[)]?",
|
||
in_context: "(^|[[:space:]])<match>|<atom-keyword><match></",
|
||
replace: "<i-auto>&</i-auto>") +
|
||
# step 8 : automatic capitalization, but not after "("
|
||
replace@(
|
||
match: "([ ]*: |—| — )" # preceded by this
|
||
+ "([[:lower:]])" # match this
|
||
+ "(?![)])", # not followed by this
|
||
replace: { _1 + to_upper(_2) }) +
|
||
# step 9 : spellcheck
|
||
{ if set.mark_errors then
|
||
check_spelling(
|
||
language: language().spellcheck_code,
|
||
extra_dictionary: "/magic.mse-game/magic-words",
|
||
extra_match: additional_text_words
|
||
)
|
||
else input
|
||
}
|
||
|
||
|
||
############################################################## Other boxes
|
||
|
||
# the flavor text filter
|
||
# - makes all text italic
|
||
flavor_text_filter :=
|
||
# step 1 : remove italic tags
|
||
remove_tag@(tag: "<i-flavor>") +
|
||
# step 2 : surround by <i> tags
|
||
{ "<i-flavor>" + input + "</i-flavor>" } +
|
||
# curly quotes
|
||
curly_quotes +
|
||
# spellcheck
|
||
{ if set.mark_errors
|
||
then check_spelling(language:language().spellcheck_code)
|
||
else input
|
||
}
|
||
|
||
# Move the cursor past the separator in the p/t and type boxes
|
||
type_over_pt := replace@(match:"/$", replace:"")
|
||
type_over_type := replace@(match:" ?[-:]$", replace:"")
|
||
|
||
super_type_filter := {
|
||
input := remove_tag(tag: "<word-list-")
|
||
input := type_over_type()
|
||
tag := "word-list-type" # TODO: localize
|
||
"<{tag}>{input}</{tag}>"
|
||
}
|
||
|
||
break_subtypes := split_text@(match: " +|<atom-sep>[^<]*</atom-sep>", include_empty:false)
|
||
sub_type_filter := {
|
||
input := remove_tag(tag: "<word-list-")
|
||
input := remove_tag(tag: "<soft")
|
||
lang := language()
|
||
# What word list to use?
|
||
list_type_rest := if lang.is_creature(type) then "class"
|
||
else if lang.is_land(type) then "land"
|
||
else if lang.is_artifact(type) then "artifact"
|
||
else if lang.is_enchantment(type) then "enchantment"
|
||
else if lang.is_spell(type) then "spell"
|
||
else if lang.is_planeswalker(type) then "planeswalker"
|
||
if list_type_rest != "" then (
|
||
if lang.is_creature(type) or lang.is_tribal(type) then (
|
||
list_type_first := "race"
|
||
) else (
|
||
list_type_first := list_type_rest
|
||
);
|
||
# wrap wordlist tag around each part
|
||
parts := break_subtypes()
|
||
(for each i:part in parts do
|
||
if i == 0 then
|
||
"<word-list-{list_type_first}>{part}</word-list-{list_type_first}>"
|
||
else
|
||
lang.subtype_separator + "<word-list-{list_type_rest}>{part}</word-list-{list_type_rest}>"
|
||
) +
|
||
(if length(parts) > 0 then
|
||
# Add a new box at the end
|
||
"<soft>{lang.subtype_separator}</soft><word-list-{list_type_rest}></word-list-{list_type_rest}>"
|
||
else
|
||
"<word-list-{list_type_first}></word-list-{list_type_first}>"
|
||
)
|
||
) else input # do nothing
|
||
}
|
||
|
||
# all sub types, for word list
|
||
space_to_comma := replace@(match:" ", replace:",")
|
||
only_first := replace@(match:" .*", replace:"")
|
||
only_next := replace@(match:"^[^ ]* ?", replace:"")
|
||
all_sub_types := {
|
||
for each card in set do
|
||
if contains(card.super_type) then "," + space_to_comma(to_text(card.sub_type))
|
||
}
|
||
all_races := {
|
||
for each card in set do
|
||
if is_creature(card.super_type) or is_tribal(card.super_type) then
|
||
"," + only_first(to_text(card.sub_type))
|
||
}
|
||
all_classes := {
|
||
for each card in set do
|
||
if contains(card.super_type, match:"Creature") then
|
||
"," + space_to_comma(only_next(to_text(card.sub_type)))
|
||
}
|
||
|
||
# Shape of cards, can be changed in style files
|
||
card_shape := { "normal" }
|
||
|
||
typesymbol_for :=
|
||
to_text +
|
||
replace@(match: "(Legendary|Basic|Snow|World| )", replace: "") +
|
||
{ if input == "Creature" then "creature"
|
||
else if input == "Sorcery" then "sorcery"
|
||
else if input == "Instant" then "instant"
|
||
else if input == "Artifact" then "artifact"
|
||
else if input == "Enchantment" then "enchantment"
|
||
else if input == "Land" then "land"
|
||
else if input == "Planeswalker" then "planeswalker"
|
||
else "multitype"
|
||
}
|
||
typesymbol_type := { typesymbol_for(card.super_type) }
|
||
|
||
#Script to make magic-mana-future compatible w/ other templates
|
||
colorless_color := { "c" }
|
||
|
||
|
||
############################################################## Statistics utilities
|
||
|
||
# Converted mana cost
|
||
is_half_mana := match@(match: "1/2|[|][WUBRGS]")
|
||
is_colored_mana := match@(match: "[WUBRG]")
|
||
only_numbers := filter_text@(match: "^[0123456789]+")
|
||
cmc_split := break_text@(match: "(?ix) 1/2 | [|][WUBRG] | [0-9]+(?!/[WUBRGSCTQ2]) | [WUBRGS0-9](/[WUBRGS])\{0,4} ")
|
||
cmc := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_half_mana(sym) then 0.5
|
||
else if numbers != "" then to_int(numbers)
|
||
else 1 # all other symbols are 1
|
||
))
|
||
}
|
||
|
||
colored_mana := {to_number(
|
||
for each sym in cmc_split(to_text()) do (
|
||
numbers := only_numbers(sym)
|
||
if is_colored_mana(sym) then
|
||
if is_half_mana(sym) then 0.5 else 1
|
||
else 0
|
||
))
|
||
}
|
||
|
||
primary_card_color := {
|
||
artifact := chosen(choice:"artifact")
|
||
land := chosen(choice:"land")
|
||
multi := chosen(choice:"multicolor")
|
||
hybrid := chosen(choice:"hybrid")
|
||
if land then "land"
|
||
else if multi and input != "artifact, multicolor" then "multicolor"
|
||
else if hybrid then "hybrid"
|
||
else if artifact then "artifact"
|
||
else input
|
||
}
|
||
|
||
word_count := break_text@(match:"[^[:space:]]+") + length
|
||
line_count := split_text@(match:"\n+",include_empty:false) + length
|
||
|
||
#Remove supertypes or types to look at parts of the super_type field by themselves.
|
||
remove_supertype := replace@(match: "(Legendary|Basic|Snow|World|Tribal|Token)", replace: "")+
|
||
replace@(match: "^[ ]", replace: "")+
|
||
replace@(match: "[ ]$", replace: "")
|
||
remove_type := replace@(match: "(Artifact|Creature|Enchantment|Instant|Land|Planeswalker|Sorcery)", replace: "")+
|
||
replace@(match: "^[ ]", replace: "")+
|
||
replace@(match: "[ ]$", replace: "")
|